﻿// owner 蒋家伟

#include "QuickCastUnitTest.h"

// std
#include <iostream>
#include <ctime>

#include "UnitTestDataDefine.h"
#include "UnitTestDbgWarnDefine.h"
#include "QuickCastDefine.h"

using namespace jsdk;

namespace jsdk
{
    class Base0
    {
        DEFINE_DRIVER_BASE(Base0)
    public:
        static void fsss();
        void fun_Base0() {}
    private:
        int a = 0;
    };

    class Base1
    {
        DEFINE_DRIVER_BASE(Base1)
    public:
        void fun_Base1() {}
    private:
        int a = 0;
    };

    class Children0 : public Base0
    {
        DEFINE_DRIVER_FROM(Children0, Base0)
    public:
        void fun_Children0() {}
        int a = 0;
    };

    class Children1 : public Base1
    {
        DEFINE_DRIVER_FROM(Children1, Base1)
    public:
        void fun_Children1() {}
    };

    class Children2 : public Base0, public Base1
    {
        DEFINE_DRIVER_FROM2(Children2, Base0, Base1)
    public:
        void fun_Children2() {}
    };

    class Children3 : public Children0, public Base1
    {
        DEFINE_DRIVER_FROM2(Children3, Children0, Base1)
    public:
        void fun_Children3() {}
    };

    class Children4 : public Children1, public Base0
    {
        DEFINE_DRIVER_FROM2(Children4, Children1, Base0)
    public:
        void fun_Children4() {}
    };

    class Test : public Base0
    {
        DEFINE_DRIVER_BASE(Test)
    public:
    };

    class Test2 : public Test
    {
        DEFINE_DRIVER_FROM(Test2, Test)
    };

    class Test3
    {
        DEFINE_DRIVER_BASE(Test3)
    };
}

UNIT_TEST_START(jsdk, QuickCastUnitTest)
{
    QuickCastUnitTest test;

    bool success = test.testCastSuccess();
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"quick_cast速度测试失败", L"蒋家伟", L"2023-10-08");

    success = test.testAddressOffset();
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"quick_cast与dynamic_cast地址偏移测试", L"蒋家伟", L"2023-10-08");

    success = test.testStrongCast();
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"quick_cast强转测试", L"蒋家伟", L"2023-10-08");

    //success = test.testCastSpeed();
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"quick_cast速度测试失败", L"蒋家伟", L"2023-10-08");
    return true;
}

bool jsdk::QuickCastUnitTest::testCastSpeed() const
{
    UNIT_TEST_DBG_WARN(L"quick_cast测速中...", L"蒋家伟", L"2023-10-10");
    constexpr int count = 100'000'000;
    Children4 children4;
    Base0* pChildren4ToBase0 = dynamic_cast<Base0*>(&children4);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren4ToBase0, UnitTestUtils::combineErrorTestMsg(false, true, L"从Children4 转换到 Base0"), L"蒋家伟", L"2023-10-08");

    clock_t startTime = clock();
    // 测试从实际Children4 Base0副指针到Base1速度
    int a = 0;
    for (int i = 0; i < count; i++)
    {
        if (Base1* pBase1 = quick_cast<Base1>(pChildren4ToBase0));
        else
        {
            UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(false, UnitTestUtils::combineErrorTestMsg(false, true, L"从Base0 转换到 Base1"), L"蒋家伟", L"2023-10-08");
        }
    }
    clock_t quick_cast_value = clock() - startTime;
    startTime = clock();
    for (int i = 0; i < count; i++)
    {
        if (Base1* pBase1 = dynamic_cast<Base1*>(pChildren4ToBase0))
        {
            continue;
        }
        UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(false, UnitTestUtils::combineErrorTestMsg(false, true, L"从Base0 转换到 Base1"), L"蒋家伟", L"2023-10-08");
    }
    clock_t dynamic_cast_value = clock() - startTime;
#ifdef _DEBUG
    UNIT_TEST_DBG_WARN(L"quick_cast测速完毕 DEBUG :\n 1亿次cast速度, dynamic_cast : " + StringUtils::toWString(dynamic_cast_value) + L" ms ; quick_cast : " + StringUtils::toWString(quick_cast_value) + L" ms", L"蒋家伟", L"2023-10-10");
    //UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(quick_cast_value < dynamic_cast_value, UnitTestUtils::combineErrorTestMsg(false, true, L"dynamic_cast Debug模式下速度小于 quick_cast "), L"蒋家伟", L"2023-10-10");
#else
    UNIT_TEST_DBG_WARN(L"quick_cast测速完毕 Release :\n 1亿次cast速度, dynamic_cast : " + StringUtils::toWString(dynamic_cast_value) + L" ms ; quick_cast : " + StringUtils::toWString(quick_cast_value) + L" ms", L"蒋家伟", L"2023-10-10");
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(quick_cast_value * 3 < dynamic_cast_value, UnitTestUtils::combineErrorTestMsg(false, true, L"dynamic_cast Release速度约为 quick_cast 三分之一"), L"蒋家伟", L"2023-10-10");
#endif // _DEBUG
    return true;
}

bool jsdk::QuickCastUnitTest::testCastSuccess() const
{
    Children4 children4;

    Base0* pChildren4ToBase0 = quick_cast<Base0>(&children4);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren4ToBase0, UnitTestUtils::combineErrorTestMsg(false, true, L"从Children4 转换到 Base0"), L"蒋家伟", L"2023-10-08");
    pChildren4ToBase0->fun_Base0();

    Children4* pBase0ToChildren4 = quick_cast<Children4>(pChildren4ToBase0);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0ToChildren4, UnitTestUtils::combineErrorTestMsg(false, true, L"从Base0 转换到 Children4"), L"蒋家伟", L"2023-10-08");
    pBase0ToChildren4->fun_Children4();

    Children1* pChildren4ToChildren1 = quick_cast<Children1>(pBase0ToChildren4);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren4ToChildren1, UnitTestUtils::combineErrorTestMsg(false, true, L"从Children4 转换到 Children1"), L"蒋家伟", L"2023-10-08");
    pChildren4ToChildren1->fun_Children1();

    Base1* pChildren4ToBase1 = quick_cast<Base1>(pBase0ToChildren4);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren4ToBase1, UnitTestUtils::combineErrorTestMsg(false, true, L"从Children4 转换到 Base1"), L"蒋家伟", L"2023-10-08");
    pChildren4ToBase1->fun_Base1();

    Children3* pChildren4ToChildren3 = quick_cast<Children3>(pBase0ToChildren4);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(!pChildren4ToChildren3, UnitTestUtils::combineErrorTestMsg(true, false, L"从Children4 转换到 Children3"), L"蒋家伟", L"2023-10-08");

    Children2 children2;
    Base0* pChildren2ToBase0 = quick_cast<Base0>(&children2);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren2ToBase0, UnitTestUtils::combineErrorTestMsg(false, true, L"从children2 转换到 Base0"), L"蒋家伟", L"2023-10-08");
    pChildren2ToBase0->fun_Base0();

    Base1* pChildren2ToBase1 = quick_cast<Base1>(pChildren2ToBase0);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren2ToBase1, UnitTestUtils::combineErrorTestMsg(false, true, L"从children2 转换到 Base1"), L"蒋家伟", L"2023-10-08");
    pChildren2ToBase1->fun_Base1();

    Base0 base0;
    Base0* pBase0ToBase0 = quick_cast<Base0>(&base0);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0ToBase0, UnitTestUtils::combineErrorTestMsg(false, true, L"从base0 转换到 base0"), L"蒋家伟", L"2023-10-08");
    pBase0ToBase0->fun_Base0();

    Test test;
    Base0* pBaseTest = quick_cast<Base0>(&test);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(!pBaseTest, UnitTestUtils::combineErrorTestMsg(true, false, L"从test 转换到 Base0"), L"蒋家伟", L"2023-10-08");

    Children0 children0;
    Test* pTest = quick_cast<Test>(&children0);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(!pTest, UnitTestUtils::combineErrorTestMsg(true, false, L"从Children0 转换到 Test"), L"蒋家伟", L"2023-10-08");

    Test2* pTest2 = quick_cast<Test2>(&test);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(!pTest2, UnitTestUtils::combineErrorTestMsg(true, false, L"从Test 转换到 Test2"), L"蒋家伟", L"2023-10-08");

    const Children3 children3;
    const Base1* pBase1_dynamic = dynamic_cast<const Base1*>(&children3);
    const Base1* pBase1_quick = quick_cast<Base1>(&children3);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1_dynamic == pBase1_quick, UnitTestUtils::combineErrorTestMsg((uint64_t)pBase1_quick, (uint64_t)pBase1_dynamic, L"quick_cast与dynamic_cast地址偏移对比"), L"蒋家伟", L"2023-11-23");

    return true;
}

bool jsdk::QuickCastUnitTest::testAddressOffset() const
{
    // 多继承情况下,第一个继承的父类地址与当前相同，而第二个继承的父类，调用时根据内存布局偏移第一个继承父类的大小(字节对齐,不一定是正好sizeof(第一个父类))
    // 因此需要测试
    Children2 children2;
    Base1* pBase1_dynamic = dynamic_cast<Base1*>(&children2);
    Base1* pBase1_quick = quick_cast<Base1>(&children2);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1_dynamic == pBase1_quick, UnitTestUtils::combineErrorTestMsg((uint64_t)pBase1_quick, (uint64_t)pBase1_dynamic, L"quick_cast与dynamic_cast地址偏移对比"), L"蒋家伟", L"2023-11-23");

    Children3 children3;
    pBase1_dynamic = dynamic_cast<Base1*>(&children3);
    pBase1_quick = quick_cast<Base1>(&children3);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1_dynamic == pBase1_quick, UnitTestUtils::combineErrorTestMsg((uint64_t)pBase1_quick, (uint64_t)pBase1_dynamic, L"quick_cast与dynamic_cast地址偏移对比"), L"蒋家伟", L"2023-11-23");

    Base0* pBase0_dynamic = dynamic_cast<Base0*>(&children3);
    Base0* pBase0_quick = quick_cast<Base0>(&children3);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0_dynamic == pBase0_quick, UnitTestUtils::combineErrorTestMsg((uint64_t)pBase0_quick, (uint64_t)pBase0_dynamic, L"quick_cast与dynamic_cast地址偏移对比"), L"蒋家伟", L"2023-11-23");

    Children0* pChildren0_dynamic = dynamic_cast<Children0*>(&children3);
    Children0* pChildren0_quick = quick_cast<Children0>(&children3);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pChildren0_dynamic == pChildren0_quick, UnitTestUtils::combineErrorTestMsg((uint64_t)pChildren0_quick, (uint64_t)pChildren0_dynamic, L"quick_cast与dynamic_cast地址偏移对比"), L"蒋家伟", L"2023-11-23");

    return true;
}

bool jsdk::QuickCastUnitTest::testStrongCast() const
{
    // 测试强转其他类型后是否依旧能quick_cast成功
    Children0 children0;
    Base0* pBase0 = quick_cast<Base0>((Children1*)(&children0));
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0, UnitTestUtils::combineErrorTestMsg(false, true, L"children0强转Children1 quick_cast->Base0"), L"蒋家伟", L"2023-11-30");
    Base0* pBase0_1 = quick_cast<Base0>(&children0);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0_1 == pBase0, UnitTestUtils::combineErrorTestMsg(false, true, L"children0 quick_cast->Base0"), L"蒋家伟", L"2023-11-30");

    Children1 children1;
    Base1* pBase1 = quick_cast<Base1>(&children1);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1, UnitTestUtils::combineErrorTestMsg(false, true, L"children1 quick_cast->pBase1"), L"蒋家伟", L"2023-11-30");

    Base0* pBase0_2 = quick_cast<Base0>(&children1);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0_2 == nullptr, UnitTestUtils::combineErrorTestMsg(true, false, L"children1 quick_cast->Base0"), L"蒋家伟", L"2023-11-30");

    Base1* pBase1_1 = quick_cast<Base1>((Test2*)&children1);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1_1 == pBase1, UnitTestUtils::combineErrorTestMsg(false, true, L"children1强转Test2 quick_cast->Base1"), L"蒋家伟", L"2023-11-30");

    Children2 children2;
    Base1* pBase1_2 = quick_cast<Base1>(&children2);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1_2, UnitTestUtils::combineErrorTestMsg(false, true, L"children2 quick_cast->pBase1"), L"蒋家伟", L"2023-11-30");

    Base0* pBase0_3 = quick_cast<Base0>(&children2);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0_3, UnitTestUtils::combineErrorTestMsg(false, true, L"children2 quick_cast->Base0"), L"蒋家伟", L"2023-11-30");

    Base1* pBase1_3 = quick_cast<Base1>((Base0*)&children2);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase1_3 == pBase1_2, UnitTestUtils::combineErrorTestMsg(false, true, L"children2强转Test3 quick_cast->Base1"), L"蒋家伟", L"2023-11-30");

    Base0* pBase0_4 = quick_cast<Base0>((Test3*)&children2);
    UNIT_TEST_DBG_WARN_AND_RETURN_FALSE_UNLESS(pBase0_4 == pBase0_3, UnitTestUtils::combineErrorTestMsg(false, true, L"children2强转Test3 quick_cast->Base0"), L"蒋家伟", L"2023-11-30");

    return true;
}
